package org.social.manager;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.bean.StoreInfo;
import org.bean.StoreInfo.ServerLimit;
import org.bean.StoreInfo.UpdateCommodity;
import org.bean.StoreInfo.UpdateStore;
import org.cfg.CommodityCfg;
import org.cfg.StoreCfg;
import org.cfg.cache.CommodityCfgCache;
import org.cfg.cache.StoreCfgCache;
import org.constant.ActionEnum;
import org.constant.ServerTypeEnum;
import org.constant.StoreConstant;
import org.constant.smallkey.SocialDiscreteDataSmallKey;
import org.interfaces.Refresher;
import org.remote.game.RemoteGameServer;
import org.social.db.bean.CommodityBuyRecord;
import org.social.db.bean.SocialDiscreteData;
import org.social.db.cache.CommodityBuyRecordCache;
import org.social.db.cache.SocialDiscreteDataCache;
import org.springframework.scheduling.support.CronSequenceGenerator;
import org.utils.RemoteUtil;

import com.google.common.collect.Maps;
import com.sojoys.artifact.tools.ToolMap;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * @author : DengYing
 * @CreateDate : 2017年11月10日 下午3:31:15
 * @Description ：全服限购商品管理器
 */
public class StoreManager {
	
	
	static final Log log = LogFactory.get(StoreManager.class);
	
	private StoreManager() {
	}

	private static StoreManager ME = new StoreManager();

	public static StoreManager me() {
		return ME;
	}
	
	
	public void notifyRemote(ServerTypeEnum type,String gameServerId) {
		Date nowDate = new Date();
		
		StoreInfo storeRefreshInfo = new StoreInfo(ActionEnum.DEFAULT); 
		// 全服限购商品购买记录
		List<CommodityBuyRecord> list = CommodityBuyRecordCache.me().loadAll();
		for (CommodityBuyRecord commodityBuyRecord : list) {
			storeRefreshInfo.getServerLimits().add(new ServerLimit(commodityBuyRecord.getCommodityId(), commodityBuyRecord.getNowBuyCount(), commodityBuyRecord.getTotalBuyCount()));
		}
		
		List<StoreCfg> storeCfgList = StoreCfgCache.me().getAll();
		
		for (StoreCfg storeCfg : storeCfgList) {
			if (StrUtil.isNotBlank(storeCfg.getAutoRefreshCorn())) {
				// 设置表达式				
				CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(storeCfg.getAutoRefreshCorn());
				// 取得商店信息
				SocialDiscreteData socialDiscreteData = getStoreLastAutoRefreshData();
				// 取得当前商城最后刷新时间
				Date lastRefreshDate = ToolMap.getDate(storeCfg.getId(),(Map) socialDiscreteData.getData(), nowDate);
				
				storeRefreshInfo.getUpdateStores().add(new UpdateStore(storeCfg.getId(), lastRefreshDate, cronSequenceGenerator.next(nowDate)));
			}
		}
		List<CommodityCfg> commoditys = CommodityCfgCache.me().getAll();
		for (CommodityCfg commodityCfg : commoditys) {
			if (StrUtil.isNotBlank(commodityCfg.getAutoRefreshCorn())) {
				// 设置表达式				
				CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(commodityCfg.getAutoRefreshCorn());
				// 取得商品信息
				SocialDiscreteData socialDiscreteData = getCommodityLastAutoRefreshData();
				// 取得当前商品最后刷新时间
				Date lastRefreshDate = ToolMap.getDate(commodityCfg.getId(),(Map) socialDiscreteData.getData(),nowDate);
				
				storeRefreshInfo.getUpdateCommoditys().add(new UpdateCommodity(commodityCfg.getId(), lastRefreshDate, cronSequenceGenerator.next(nowDate)));
			}
		}
		storeRefreshInfo.setAction(ActionEnum.DEFAULT);
		
//		if (!storeRefreshInfo.isEmpty()) {
			switch (type) {
			case GAME_SERVER:
				RemoteUtil.gameAsyn(gameServerId).noticeStore(storeRefreshInfo);
				break;
			default:
				break;
			}
//		}
	}

	
	private SocialDiscreteData getStoreLastAutoRefreshData() {
		SocialDiscreteData socialDiscreteData = SocialDiscreteDataCache.me().getByKey(SocialDiscreteDataSmallKey.STORE_LAST_AUTO_REFRESH_TIME);
		if (socialDiscreteData == null) {
			socialDiscreteData = new SocialDiscreteData(0, SocialDiscreteDataSmallKey.STORE_LAST_AUTO_REFRESH_TIME, Maps.newHashMap());
			socialDiscreteData.insert();
		}
		return socialDiscreteData;
	}
	
	private SocialDiscreteData getCommodityLastAutoRefreshData() {
		SocialDiscreteData socialDiscreteData = SocialDiscreteDataCache.me().getByKey(SocialDiscreteDataSmallKey.COMMODITY_LAST_AUTO_REFRESH_TIME);
		if (socialDiscreteData == null) {
			socialDiscreteData = new SocialDiscreteData(0, SocialDiscreteDataSmallKey.COMMODITY_LAST_AUTO_REFRESH_TIME, Maps.newHashMap());
			socialDiscreteData.insert();
		}
		return socialDiscreteData;
	}
	
	/**
	 * 自动刷新
	 * @throws ParseException
	 */
	public void autoRefresh() {
		List<StoreCfg> storeCfgList = StoreCfgCache.me().getAll();
		
		Date nowDate = new Date();
		
		StoreInfo storeRefreshInfo = new StoreInfo(ActionEnum.RESET); 
		
		for (StoreCfg store : storeCfgList) {
			
			if (StrUtil.isNotBlank(store.getAutoRefreshCorn())) {
				// 取得商店信息
				SocialDiscreteData socialDiscreteData = getStoreLastAutoRefreshData();
				Map data = (Map) socialDiscreteData.getData();
				// 取得当前商城最后刷新时间
				Date lastRefreshDate = ToolMap.getDate(store.getId(),data, nowDate);
				// 设置表达式				
				CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(store.getAutoRefreshCorn());
				
				if (isRefresh(nowDate, lastRefreshDate, cronSequenceGenerator, store.new StoreRefresher())) {
					// 更新下一次刷新时间
					store.setNextRefreshDate(cronSequenceGenerator.next(nowDate));
					
					List<CommodityCfg> commoditys = CommodityCfgCache.me().getByStoreId(store.getId());
					for (CommodityCfg commodityCfg : commoditys) {
						updateServerBuyRecord(storeRefreshInfo, commodityCfg);
					}

					// 更新最后刷新时间
					data.put(store.getId(), nowDate);
					socialDiscreteData.update();
					
					storeRefreshInfo.getUpdateStores().add(new UpdateStore(store.getId(), nowDate, store.getNextRefreshDate()));
				}
					
			}else {
				// 取得商品信息
				List<CommodityCfg> commoditys = CommodityCfgCache.me().getByStoreId(store.getId());
				SocialDiscreteData socialDiscreteData = getCommodityLastAutoRefreshData();
				for (CommodityCfg commodityCfg : commoditys) {
					if (StrUtil.isNotBlank(commodityCfg.getAutoRefreshCorn())) {
						// 取得商品信息
						Map data = (Map) socialDiscreteData.getData();
						// 取得当前商品最后刷新时间
						Date lastRefreshDate = ToolMap.getDate(commodityCfg.getId(),data,nowDate);
						// 设置表达式				
						CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(commodityCfg.getAutoRefreshCorn());
						
						if (isRefresh(nowDate, lastRefreshDate, cronSequenceGenerator, commodityCfg.new CommodityRefresher())) {
							// 更新下一次刷新时间
							commodityCfg.setNextRefreshDate(cronSequenceGenerator.next(nowDate));

							updateServerBuyRecord(storeRefreshInfo, commodityCfg);

							// 更新最后刷新时间
							data.put(commodityCfg.getId(), nowDate);
							socialDiscreteData.update();
							
							storeRefreshInfo.getUpdateCommoditys().add(new UpdateCommodity(commodityCfg.getId(), nowDate, commodityCfg.getNextRefreshDate()));
						}
					}
				}
			}
			
			if (!storeRefreshInfo.isEmpty()) {
				storeRefreshInfo.setAction(ActionEnum.RESET);
				// 通知商店刷新
				RemoteGameServer remoteGameServer = RemoteUtil.gameTopic();
				remoteGameServer.noticeStore(storeRefreshInfo);
			}
		}
	}

	/**
	 * 检查是否刷新
	 *
	 * @param nowDate               当前时间
	 * @param lastRefreshDate       上次刷新时间
	 * @param cronSequenceGenerator cron表达式解析器
	 * @param refresher             刷新对象
	 */
	private boolean isRefresh(Date nowDate,
							  Date lastRefreshDate,
							  CronSequenceGenerator cronSequenceGenerator,
							  Refresher refresher) {

		if (refresher.getNextRefreshDate() == null) {
            // 正常的下一次执行时间
            Date nextRefreshDate = cronSequenceGenerator.next(lastRefreshDate);
            refresher.setNextRefreshDate(cronSequenceGenerator.next(nowDate));
            // 算出应该执行时间节点
            if(nextRefreshDate.before(nowDate)){
                return true;
            }
        }else if (refresher.getNextRefreshDate().before(nowDate)) {
			return true;
        }
		return false;
	}

	/**
	 * 更新购买记录
	 *
	 * @param storeRefreshInfo 商城刷新信息
	 * @param commodityCfg     商品配置
	 */
	private void updateServerBuyRecord(StoreInfo storeRefreshInfo, CommodityCfg commodityCfg) {
		if (commodityCfg.getLimitType() == StoreConstant.LIMIT_SERVER_TYPE) {
            CommodityBuyRecord commodityBuyRecord = CommodityBuyRecordCache.me().getByCommodityId(commodityCfg.getId());
            if (commodityBuyRecord != null) {
                commodityBuyRecord.setNowBuyCount(0);
                commodityBuyRecord.update();
                storeRefreshInfo.getServerLimits().add(new ServerLimit(commodityBuyRecord.getCommodityId(), commodityBuyRecord.getNowBuyCount(), commodityBuyRecord.getTotalBuyCount()));
            }
        }
	}

	public static void main(String[] args) throws ParseException {
		CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator("0 0 0 1 * ?");  
		System.out.println(cronSequenceGenerator.next(new Date()));
	}
}
